/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package demo.parallelcore;

import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * A demo shows how does Stream's aggregation works. Demo shows
 * 1. Sum operation on stream interface
 * 2. Use Stream's count operation as Function output
 * @author tyan
 */
public class Aggregation extends DemoHelper { 
    /**
     * Calculate total product's price.
     * @return  total product's price
     */
    public static double totalProductPrice() {
        return products.parallelStream().
                //map every product to its price
                mapToDouble(p -> p.getUnitPrice() * p.getUnitsInStock()).
                //caculation total price
                sum();
    }

   /**
     * Get every customer's order count that order meets the predicate<p>
     * It's possible some customers who don't have any order in given period.
     * @param    predicate a order predicate
     * @return   map for customer's name and its number of order meets the
     *           predicate
    */
    public static Map<String, Long> customerAndOrderCount(
            Predicate<Order> predicate) {
        return customers.stream().
                //convert customers into a map that key is customer's name and 
                //value is number of orders which filter by predicate
                collect(Collectors.toMap(
                    Customer::getCompanyName, c ->
                        c.getOrders().parallelStream().
                        //filter orders' stream by given predicate
                        filter(predicate).
                        //get number of order which filter by given predicate
                        count()
                ));
    }
}
